﻿using System;
using System.IO.Ports;
using Oxage.Models;
using Oxage.Common;

namespace Oxage.Drivers
{
	public class SerialPortConnector : ConnectorBase
	{
		#region Members
		private SerialPort port;
		private SerialPortModel model;
		#endregion

		#region Constructor
		public SerialPortConnector()
		{
			port = new SerialPort();
			model = new SerialPortModel();

			//Default values
			port.PortName = model.PortName;
			port.BaudRate = model.BaudRate;
			port.DataBits = model.DataBits;
			port.Parity = model.Parity;
			port.StopBits = model.StopBits;
			port.Handshake = model.Handshake;
			port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
		}
		#endregion

		#region IMachineController Members
		public override string Name
		{
			get { return "Serial port"; }
		}

		/// <summary>
		/// Opens a serial port connection.
		/// </summary>
		public override void Open()
		{
			port.Open();
		}

		/// <summary>
		/// Closes the serial port connection.
		/// </summary>
		public override void Close()
		{
			port.Close();
		}

		/// <summary>
		/// Sends bytes to the connected server.
		/// </summary>
		/// <param name="data"></param>
		public override void Write(byte[] data)
		{
			port.Write(data, 0, data.Length);
		}
		#endregion

		#region Simulator
		private int cursor = 0;
		private byte[] buffer = new byte[5];

		private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
		{
			//For simulator
			//Protocol: [STX] + mask_x + mask_y + mask_z + [ETX]

			while (port.BytesToRead > 0)
			{
				int i = port.ReadByte();
				if (i >= 0x00 && i <= 0xFF)
				{
					byte b = (byte)i;
					if (cursor <= 0)
					{
						//Waiting for the STX byte - start of packet
						if (b == Ascii.STX)
						{
							cursor = 0;
							buffer = new byte[5];
							buffer[cursor++] = Ascii.STX;
						}
					}
					else
					{
						//Read mask byte
						if (cursor <= 3)
						{
							buffer[cursor++] = b;
						}
						//Waiting for the ETX byte - end of packet
						else if (b == Ascii.ETX)
						{
							buffer[cursor] = Ascii.ETX;
							OnSimulatorBlockReceived(buffer);
							cursor = 0;
						}
					}
				}
			}
		}

		public event EventHandler<EventArgs<byte[]>> SimulatorBlockReceived;
		protected virtual void OnSimulatorBlockReceived(byte[] buffer)
		{
			if (SimulatorBlockReceived != null)
			{
				SimulatorBlockReceived(this, new EventArgs<byte[]>(buffer));
			}
		}
		#endregion
	}
}
